#!/bin/bash

# 配置文件路径
CONFIG_FILE="./services.conf"


# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# 检查配置文件是否存在
# 检查配置文件是否存在
if [ ! -f "$CONFIG_FILE" ]; then
    CONFIG_FILE="/data/tools/gzlr/services.conf"
    if [ ! -f "$CONFIG_FILE" ]; then
        echo -e "${RED}错误：配置文件不存在！请添加配置文件：$CONFIG_FILE。${NC}"
        exit 1
    fi
fi

# 处理配置文件中的Windows换行符
dos2unix "$CONFIG_FILE" 2>/dev/null || sed -i 's/\r//' "$CONFIG_FILE"

# 加载配置文件
source "$CONFIG_FILE"

# 获取所有配置的应用
declare -a APP_LIST
for var in $(compgen -v | grep "^app[0-9]*_name"); do
    app_num=${var%_*}
    APP_LIST+=("$app_num")
done

# 测试端口是否使用中
is_port_in_use() {
    local port=$1
    if [ -z "$port" ]; then
        return 1
    fi
    if lsof -i:"$port" >/dev/null 2>&1; then
        return 0
    else
        return 1
    fi
}

# 获取Tomcat是否安装守护进程模式
is_install_tomcat_daemon_mode() {
    local instance=$1
    local tomcat_path_var="${instance}_workdir"
    local tomcat_path="${!tomcat_path_var}"
    if [ -z "$tomcat_path" ]; then
        return 1
    fi
    local daemon_script="$tomcat_path/bin/daemon.sh"
    local jsvc_script="$tomcat_path/bin/jsvc"
    if [ -f "$daemon_script" ] && [ -f "$daemon_script" ] && [ -x "$daemon_script" ] && [ -x "$daemon_script" ] ; then
        # 修改获取JAVA_HOME的逻辑，使用更精确的匹配
        local _java_home=$(grep "^JAVA_HOME=" "$daemon_script" | grep -v '"\$2"' | grep -v 'dirname' | grep -v 'cd.*pwd' | tail -n 1 | cut -d'=' -f2)
        
        # 如果JAVA_HOME是用引号括起来的，去掉引号
        _java_home=$(echo "$_java_home" | sed -e 's/^"//' -e 's/"$//')
        
        # 如果存在多行定义，确保只取最后一个定义的值
        if [[ "$_java_home" == *$'\n'* ]]; then
            _java_home=$(echo "$_java_home" | tail -n 1)
        fi
        
        if [ -z "$_java_home" ]; then
            echo -e "${RED}Daemon模式已安装，但未配置JAVA_HOME，请检查daemon.sh文件。${NC}"
            return 1
        fi
        if [ ! -x "$_java_home/bin/java" ]; then
            echo -e "${RED}Daemon模式已安装，但JAVA_HOME指向的Java环境变量无效，请检查daemon.sh文件。${NC}"
            echo -e "${RED}无效JAVA_HOME：$_java_home${NC}"
            return 1
        fi
        _java_version=$($_java_home/bin/java -version 2>&1 | awk -F '"' '/version/ {print $2}')
        echo -e "${YELLOW}Daemon模式已安装，JAVA_HOME: ${NC}${_java_home}，${YELLOW}JAVA版本${NC}: ${_java_version}"
        return 0
    else
        echo -e "${RED}未安装Daemon模式，请先安装。${NC}"
        return 1
    fi
}

# 检查服务状态
check_service_status() {
    local instance=$1
    local pid_file_var="${instance}_pid_file"
    local workdir_var="${instance}_workdir"

    local workdir="${!workdir_var}"
    local pid_file="${!pid_file_var}"
    local pid_file_path=$(join_paths "$workdir" "$pid_file")

    if [ -z "$workdir" ] || ! cd "$workdir" 2>/dev/null; then
        return 1
    fi

    if [ -f "$pid_file_path" ]; then
        pid=$(cat "$pid_file_path")
        if [[ "$pid" =~ ^[0-9]+$ ]] && kill -0 "$pid" 2>/dev/null; then
            echo -e "${GREEN}运行中 (PID: $pid)${NC}"
            return 0
        else
            echo -e "${RED}已停止 (PID文件存在但进程无效: $pid_file_path)${NC}"
            return 1
        fi
    fi
    echo -e "${RED}已停止${NC}"
    return 1
}

# 获取进程ID的通用方法
get_service_pid() {
    local instance=$1
    local workdir_var="${instance}_workdir"
    local pid_file_var="${instance}_pid_file"

    local workdir="${!workdir_var}"
    local _pid_file="${!pid_file_var}"
    local pid_file=$(join_paths "$workdir" "$_pid_file")
    local pid=""

    # 修正pid文件路径的构造
    if [ -f "$pid_file" ]; then
        pid=$(cat "$pid_file")
        # 验证PID是否有效 - 只取第一个PID
        pid=$(echo "$pid" | awk '{print $1}')
        if ps -p $pid > /dev/null 2>&1; then
            echo $pid
            return 0
        else
            # PID文件存在但进程不存在，清理无效的PID文件
            rm -f "$pid_file"
        fi
    fi
    
    # 如果PID文件不存在或无效，尝试通过进程名查找
    pid=$(pgrep -f "$workdir" | head -n 1)
    if [ -n "$pid" ]; then
        echo $pid
        return 0
    fi
    
    # 都没找到，返回空
    echo ""
    return 1
}

# 拼接路径
join_paths() {
    local path1="${1:-}" # 工作目录路径
    local path2="${2:-}" # 文件路径
    
    # 两个路径都为空，返回空字符串
    if [ -z "$path1" ] && [ -z "$path2" ]; then
        echo ""
        return 0
    fi
    
    # 只有一个路径有值，直接返回有值的路径
    if [ -z "$path1" ]; then
        echo "$path2"
        return 0
    fi
    if [ -z "$path2" ]; then
        echo "$path1"
        return 0
    fi
    
    # 如果path2以-开头，表示特殊参数，去除掉-后返回
    if [[ "$path2" == -* ]]; then
        path2="${path2:1}"  # 去除开头的-
        echo "$path2"
        return 0
    fi
    
    # 标准化路径，移除结尾和开头的多余斜杠
    local norm_path1="${path1%/}"
    local norm_path2="${path2#/}"
    
    # 特殊情况: 如果path1是根目录，不要去除斜杠
    if [ "$path1" = "/" ]; then
        norm_path1="/"
    fi
    
    # 拼接并返回
    echo "${norm_path1}/${norm_path2}"
    return 0
}

get_service_java_home() {
    local instance=$1
    local java_home_var="${instance}_java_home"

    # 优先使用实例特定的java_home
    local java_home="${!java_home_var}"
    if [ -z "$java_home" ]; then
        # 这里之前写错了，应该直接用全局变量名
        if [ -n "$java_home" ]; then
            echo "$java_home"
            return 0
        else
            echo -e "${RED}Java环境变量未设置，请先在services.conf中设置java_home变量${NC}" >&2
            return 1
        fi
    fi

    echo "$java_home"
    return 0
}

# 安装Tomcat守护进程模式
install_tomcat_daemon_mode() {
    local instance=$1
    local name_var="${instance}_name"
    local workdir_var="${instance}_workdir"

    local name="${!name_var}"
    local _java_home=$(get_service_java_home "$instance")
    local workdir="${!workdir_var}"
    local binDir="${workdir}/bin"

    echo "正在安装 $name 的守护进程模式..."
    
    if [ ! -f "$binDir/daemon.sh" ]; then
        if [ -f "$binDir/daemon.sh.bak" ]; then
            cp "$binDir/daemon.sh.bak" "$binDir/daemon.sh"
        else
            echo -e "${RED}错误: 缺少$binDir/daemon.sh文件，请重新安装Tomcat！${NC}"
            return 1
        fi
    fi

    if [ ! -x "$binDir/daemon.sh" ]; then
        chmod +x "$binDir/daemon.sh"
    fi

    if [ -f "$binDir/jsvc" ]; then
        if [ ! -x "$binDir/jsvc" ]; then 
            chmod +x "$binDir/jsvc"
        fi 
        echo -e "${YELLOW}警告: $binDir/jsvc 已存在，可能是之前安装过守护进程模式。${NC}"
        read -p "是否覆盖安装？(y|n): " confirm
        if [ "$confirm" != "y" ]; then
            echo -e "${RED}取消安装守护进程模式。${NC}"
            return 0
        else
            if [ -f "$binDir/daemon.sh.bak" ]; then
                cp "$binDir/daemon.sh.bak" "$binDir/daemon.sh"
            fi
        fi
    fi

    # 判断 java_home 不能为空
    if [ ! -f "$_java_home/bin/java" ]; then
        echo -e "${RED}Java环境变量未设置，请先设置${instance}_java_home。${NC}"
        return 1
    fi
    
    if [ -z "$workdir" ]; then
        echo -e "${RED}工作目录未设置，无法安装守护进程模式！${NC}"
        return 1
    fi
    
    # 检查必要文件是否存在
    if [ ! -f "$binDir/commons-daemon-native.tar.gz" ]; then
        echo -e "${RED}找不到commons-daemon-native.tar.gz文件！${NC}"
        return 1
    fi

    # 解压daemon源码
    cd "$binDir"
    tar xzf commons-daemon-native.tar.gz
    
    # 找到解压后的目录
    local daemon_src_dir=$(find . -maxdepth 1 -type d -name "commons-daemon-*-native-src" | head -n 1)
    if [ -z "$daemon_src_dir" ]; then
        echo -e "${RED}无法找到解压后的commons-daemon目录！${NC}"
        return 1
    fi

    # 编译jsvc
    cd "$daemon_src_dir/unix"
    ./configure --with-java="$_java_home"
    if [ $? -ne 0 ]; then
        echo -e "${RED}配置编译环境失败！${NC}"
        return 1
    fi

    make
    if [ $? -ne 0 ]; then
        echo -e "${RED}编译失败！${NC}"
        return 1
    fi

    # 复制jsvc到bin目录
    cp jsvc "$binDir/"
    chmod +x "$binDir/jsvc"

     # 修改daemon.sh配置
    if [ -f "$binDir/daemon.sh" ]; then

        if [ ! -f "$binDir/daemon.sh.bak" ]; then
            # 备份原始文件
            cp "$binDir/daemon.sh" "$binDir/daemon.sh.bak"
        fi

        # 更新默认用户为root
        sed -i 's/test ".$TOMCAT_USER" = . && TOMCAT_USER=tomcat/test ".$TOMCAT_USER" = . \&\& TOMCAT_USER=root/' "$binDir/daemon.sh"
        
        # 在PRG="$0"行后添加JAVA_HOME配置
        sed -i '/^PRG="$0"$/a JAVA_HOME='"$_java_home" "$binDir/daemon.sh"
        
        # 修改JAVA_OPTS配置，使用用户输入的内存值
        local xms="256m"
        local xmx="2048m"
        
        read -p "请输入最小内存值(例如:256m,1g, 默认${xms}): " input_xms
        if [ -n "$input_xms" ]; then
            if [[ "$input_xms" =~ ^[0-9]+[mMgG]$ ]]; then
                xms="$input_xms"
            else
                echo -e "${RED}输入格式错误，使用默认值：${xms}${NC}"
            fi
        fi
        
        read -p "请输入最大内存值(例如:2048m,2g, 默认${xmx}): " input_xmx
        if [ -n "$input_xmx" ]; then
            if [[ "$input_xmx" =~ ^[0-9]+[mMgG]$ ]]; then
                xmx="$input_xmx"
            else
                echo -e "${RED}输入格式错误，使用默认值：${xmx}${NC}"
            fi
        fi

        sed -i '0,/^JAVA_OPTS=/s|^JAVA_OPTS=.*|JAVA_OPTS="-Xms'"$xms"' -Xmx'"$xmx"' -Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8 -Duser.language=zh -Duser.region=CN -Duser.timezone=Asia/Shanghai -Dorg.apache.catalina.security.SecurityListener.UMASK=0022"|' "$binDir/daemon.sh"
        
        chmod +x "$binDir/daemon.sh"
    else
        echo -e "${RED}daemon.sh文件不存在！${NC}"
        return 1
    fi

    # 清理临时文件
    rm -rf "$binDir/$daemon_src_dir"
    # 删除旧的启动脚本
    rm -f "$binDir/startup.sh" "$binDir/shutdown.sh"

    echo -e "${GREEN} $name 守护进程模式安装完成！${NC}"
    return 0
}

show_system_java_home() {
    local java_home=$(get_service_java_home "$1")
    if [ -n "$java_home" ]; then
        # 获取java版本
        local java_version=$("$java_home/bin/java" -version 2>&1 | awk -F '"' '/version/ {print $2}')
        echo -e "${YELLOW}Java版本: ${YELLOW}${java_version}${NC}"
        echo -e "${YELLOW}Java环境变量: ${YELLOW}${java_home}${NC}"
    else
        echo -e "${RED}Java环境未设置！${NC}"
    fi
}

show_tomcat_menu() {
    local instance=$1
    local name="${instance}_name"
    while true; do
        clear
        echo -e "${BLUE}===============================================${NC}"
        echo -e "${YELLOW}        Tomcat管理: ${!name}            ${NC}"
        echo -e "${BLUE}===============================================${NC}"

        get_tomcat_status "$instance"

        echo -e "${BLUE}-----------------------------------------------${NC}"
        echo -e "${YELLOW}1)${NC} 启动服务"
        echo -e "${YELLOW}2)${NC} 停止服务"
        echo -e "${YELLOW}3)${NC} 重启服务"
        echo -e "${YELLOW}4)${NC} 查看日志"
        echo -e "${YELLOW}9)${NC} 安装Daemon模式"
        echo -e "${YELLOW}0)${NC} 返回主菜单"
        echo -e "${BLUE}-----------------------------------------------${NC}"
        read -e -p "请输入选项: " choice
        case $choice in
            1)
                read -p "确认要启动吗？(y|n): " confirm
                if [ "$confirm" = "y" ]; then
                    start_tomcat "$instance"
                    read -p "按回车继续..."
                fi
                ;;
            2)
                read -p "确认要停止吗？(y|n): " confirm
                if [ "$confirm" = "y" ]; then
                    stop_tomcat "$instance"
                    read -p "按回车继续..."
                fi
                ;;
            3)
                read -p "确认要重启吗？(y|n): " confirm
                if [ "$confirm" = "y" ]; then
                    restart_tomcat "$instance"
                    read -p "按回车继续..."
                fi
                ;;
            4)
                view_tomcat_logs "$instance"
                ;;
            9)
                read -p "确认要安装守护进程模式吗？(y|n): " confirm
                if [ "$confirm" = "y" ]; then
                    install_tomcat_daemon_mode "$instance"
                    read -p "按回车继续..."
                fi
                ;;
            0|b|B)
                break
                ;;
            *)
                echo "无效选项"
                ;;
        esac
    done
}

edit_service_config() {
    clear
    echo -e "${BLUE}===============================================${NC}"
    echo -e "${YELLOW}              编辑服务配置                    ${NC}"
    echo -e "${BLUE}===============================================${NC}"

    if [ ! -f "$CONFIG_FILE" ]; then
        echo -e "${RED}配置文件不存在，请创建：$CONFIG_FILE${NC}"
        return 1
    fi

    # 备份配置文件
    cp "$CONFIG_FILE" "${CONFIG_FILE}.bak"

    # 检查可用的编辑器
    local editors=("nano" "vim" "vi")
    local editor=""
    
    for e in "${editors[@]}"; do
        if command -v "$e" >/dev/null 2>&1; then
            editor="$e"
            break
        fi
    done

    if [ -z "$editor" ]; then
        echo -e "${RED}未找到可用的文本编辑器（需要nano、vim或vi）${NC}"
        return 1
    fi

    echo -e "${YELLOW}使用 $editor 编辑器打开配置文件...${NC}"
    echo -e "${BLUE}提示：编辑完成后按 Ctrl+X (nano) 或 :wq (vim) 保存并退出${NC}"
    sleep 1

    # 使用选定的编辑器打开配置文件
    $editor "$CONFIG_FILE"
    
    if [ $? -ne 0 ]; then
        echo -e "${RED}编辑配置文件失败。${NC}"
        echo -e "${YELLOW}是否恢复备份？(y/n)${NC}"
        read -p "" restore
        if [ "$restore" = "y" ]; then
            mv "${CONFIG_FILE}.bak" "$CONFIG_FILE"
            echo -e "${GREEN}已恢复备份文件。${NC}"
        fi
        return 1
    fi

    # 检查文件语法
    if ! bash -n "$CONFIG_FILE" >/dev/null 2>&1; then
        echo -e "${RED}配置文件包含语法错误！${NC}"
        echo -e "${YELLOW}是否恢复备份？(y/n)${NC}"
        read -p "" restore
        if [ "$restore" = "y" ]; then
            mv "${CONFIG_FILE}.bak" "$CONFIG_FILE"
            echo -e "${GREEN}已恢复备份文件。${NC}"
            return 1
        fi
    fi

    # 清理备份文件
    rm -f "${CONFIG_FILE}.bak"
    echo -e "${GREEN}配置文件已保存。${NC}"
    
    # 重新加载配置
    source "$CONFIG_FILE"
    echo -e "${GREEN}配置已重新加载。${NC}"
    return 0
}

# 处理服务菜单选项
handle_service_menu() {
    local instance=$1
    local type_var="${instance}_type"
    
    case "${!type_var}" in
        "tomcat")
            show_tomcat_menu "$instance"
            ;;
        *)
            echo -e "${RED}不支持的服务类型: ${!type_var}${NC}"
            ;;
    esac
}

# 显示主菜单
show_menu() {
    local _system_java_home=$(get_service_java_home "$1")

    clear
    echo -e "${BLUE}===============================================${NC}"
    echo -e "${YELLOW}              服务管理面板                    ${NC}"
    echo -e "${BLUE}===============================================${NC}"
    
    show_system_info
    if [ -n "$_system_java_home" ]; then
        show_system_java_home
    fi
    
    echo -e "${BLUE}-----------------------------------------------${NC}"
    for i in "${!APP_LIST[@]}"; do
        local idx=$((i+1))
        local instance="${APP_LIST[$i]}"
        local name="${instance}_name"
        local type="${instance}_type"
        printf "${YELLOW}%-3s${NC} %s (${YELLOW}%s${NC}) %s\n" \
            "$idx)" \
            "${!name}" \
            "${!type}" \
            "$(get_service_brief_info "$instance")"
    done
    echo -e "${BLUE}-----------------------------------------------${NC}"
    echo -e "${YELLOW}99)${NC} 编辑服务配置"
    echo -e "${YELLOW}0)${NC} 退出"
    echo -e "${BLUE}-----------------------------------------------${NC}"
}


# 主循环
while true; do
    show_menu
    read -p "请选择操作: " choice
    
    if [ "$choice" = "99" ]; then
        edit_service_config
    elif [ "$choice" = "0" ]; then
        echo -e "${GREEN}退出程序...${NC}"
        exit 0
    elif [[ "$choice" =~ ^[0-9]+$ ]] && [ "$choice" -gt 0 ] && [ "$choice" -le "${#APP_LIST[@]}" ]; then
        instance=${APP_LIST[$((choice-1))]}
        handle_service_menu "$instance"
    else
        echo -e "${RED}无效的选择${NC}"
    fi
    
    read -p "按回车键继续..."
done